package cn.csg.iotplatform.module.system.service.eqfile;

import cn.csg.iotplatform.framework.common.pojo.CommonResult;
import cn.csg.iotplatform.module.infra.api.file.FileApi;
import cn.csg.iotplatform.module.infra.api.file.dto.FileDownloadReqDTO;
import cn.csg.iotplatform.module.infra.dto.FileDownloadRespDTO;
import cn.csg.iotplatform.module.infra.dto.FileRespDTO;
import cn.csg.iotplatform.module.system.api.file.EqtFileClient;
import cn.csg.iotplatform.module.system.api.file.dto.EqtFileDto;
import cn.csg.iotplatform.module.system.api.file.dto.ModelAttachmentVO;
import cn.csg.iotplatform.module.system.api.file.dto.EqtFileDeleteVO;
import cn.csg.iotplatform.module.system.controller.admin.auth.vo.AuthLoginRespVO;
import cn.csg.iotplatform.module.system.controller.admin.file.vo.EqtFileSaveVO;
import cn.csg.iotplatform.module.system.dal.dataobject.user.AdminUserDO;
import cn.csg.iotplatform.module.system.enums.logger.LoginLogTypeEnum;
import cn.csg.iotplatform.module.system.service.auth.AdminAuthService;
import cn.csg.iotplatform.module.system.service.user.AdminUserService;
import cn.csg.iotplatform.module.system.dal.dataobject.logger.GkDeviceCenterApiLogDO;
import cn.csg.iotplatform.module.system.enums.DeviceCenterApiEnum;
import cn.csg.iotplatform.module.system.service.logger.GkDeviceCenterApiLogService;
import cn.csg.iotplatform.module.system.util.EqtCenterUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.body.MultipartBody;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dtflys.forest.backend.ContentType;
import com.dtflys.forest.http.ForestResponse;

import feign.okhttp.OkHttpClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.http.Consts;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import static cn.csg.iotplatform.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * @author Clqv
 * @create 2024--11--11 11:25
 */
@Service
@Slf4j
public class EqtFileServiceImpl implements EqtFileService {

    @Resource
    private EqtFileClient eqtFileClient;

    @Resource
    private FileApi fileApi;

    @Resource
    private AdminAuthService adminAuthService;

    @Resource
    private AdminUserService adminUserService;

    @Value("${iot.eqt-center.address}")
    private String deviceCenterAddress;

    @Value("${iot.eqt-center.username}")
    private String username;

    @Resource
    private GkDeviceCenterApiLogService gkDeviceCenterApiLogService;


    /**
     * 同步附件信息
     * @return
     */
    @Override
    public JSONObject syncFile(EqtFileSaveVO eqtFileSaveVO) {

        //判断参数
        if (StringUtils.isEmpty( eqtFileSaveVO.getObjectId() )){
            throw exception("业务id不能为空");
        }

        if (StringUtils.isEmpty( eqtFileSaveVO.getFileUrl() )){
            throw exception("文件url不能为空");
        }

        //根据附件url从文件服务获取到文件流
        FileRespDTO fileInfo = fileApi.getFileByUrl(eqtFileSaveVO.getFileUrl()).getData();
        if (ObjectUtil.isEmpty( fileInfo )){
            throw exception("文件信息为空，请检查文件路径是否正确");
        }

        //插入日志
        GkDeviceCenterApiLogDO gkDeviceCenterApiLogDO = new GkDeviceCenterApiLogDO();
        gkDeviceCenterApiLogDO.setRequestParam( JSONObject.toJSONString( eqtFileSaveVO ) );

        File file = null;
        InputStream inputStream = null;
        String name = "";
        try {

            FileDownloadReqDTO fileDownloadReqDTO = new FileDownloadReqDTO();
            fileDownloadReqDTO.setConfigId( fileInfo.getConfigId() );
            fileDownloadReqDTO.setPath( eqtFileSaveVO.getFileUrl() );

            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            String authorization;
            if(requestAttributes != null) {
                authorization = requestAttributes.getRequest().getHeader("Authorization");
            } else {
                AdminUserDO adminUserDO = adminUserService.getUserByUsername(username);
                AuthLoginRespVO authLoginRespVO = adminAuthService.getToken(adminUserDO);
                authorization = "Bearer " + authLoginRespVO.getAccessToken();
            }

            CommonResult<FileDownloadRespDTO> fileDownloadRespDTOCommonResult = fileApi.fileDownload(fileDownloadReqDTO, authorization);
            if (fileDownloadRespDTOCommonResult == null || !fileDownloadRespDTOCommonResult.isSuccess()) {
                throw new Exception("导入文件下载失败: " + JSON.toJSONString(fileDownloadRespDTOCommonResult));
            }
            //处理文件名
            String url = fileInfo.getUrl();
            String[] s = url.split("\\.");
            name = eqtFileSaveVO.getObjectId() + "." + s[s.length - 1];

            //转成file
            inputStream = new ByteArrayInputStream(fileDownloadRespDTOCommonResult.getData().getContent());
            file = new File(name);
            FileUtils.copyInputStreamToFile(inputStream, file);
            // file = new MockMultipartFile(ContentType.APPLICATION_OCTET_STREAM, inputStream);

        }catch (Exception e){
            gkDeviceCenterApiLogDO.setStatusCode( HttpStatus.HTTP_INTERNAL_ERROR + "" );
            gkDeviceCenterApiLogDO.setResponseResult("获取minio文件失败，异常：" + e);
            gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.SAVEATTACHMENTFILE );
            throw exception("获取minio文件失败，异常：" + e );
        }

        try {

            EqtFileDto eqtFileDto = new EqtFileDto();
            ModelAttachmentVO attachmentVO = BeanUtil.toBean(eqtFileSaveVO, ModelAttachmentVO.class);
            attachmentVO.setIotUrl(eqtFileSaveVO.getFileUrl());
            JSONObject modelAttachmentInfo = (JSONObject) JSONObject.toJSON( attachmentVO );
            eqtFileDto.setModelAttachmentInfo( modelAttachmentInfo );

            // JSONObject jsonObject = new JSONObject();
            // jsonObject.put("jobTypeCode", attachmentVO.getJobTypeCode());
            // jsonObject.put("objectId", attachmentVO.getObjectId());
            // jsonObject.put("flag", attachmentVO.getFlag());
            // eqtFileDto.setModelAttachmentInfo( jsonObject );

            // ForestResponse<JSONObject> jsonObjectForestResponse = eqtFileClient.saveAttachmentFile(EqtCenterUtil.doFormDataPostJsonHeader(JSON.toJSONString(eqtFileDto)), eqtFileDto, file);
            String resultStr = senFile(DeviceCenterApiEnum.SAVEATTACHMENTFILE.getApiUrl(), file, eqtFileDto);
            JSONObject result = JSONObject.parseObject( resultStr );
            if ( ObjectUtil.isNotEmpty( result ) && ! (HttpStatus.HTTP_OK + "").equals( result.getString("code") )){
                gkDeviceCenterApiLogDO.setStatusCode( result.getString("code") + "" );
                gkDeviceCenterApiLogDO.setResponseResult( result.toJSONString() );
                gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.SAVEATTACHMENTFILE );
                throw new Exception("调用设备中心同步附件接口失败" + (ObjectUtil.isNotEmpty( result ) ? "，" + result.getString("msg") : ""));
            }
            if ( ObjectUtil.isNotEmpty( result ) ){
                gkDeviceCenterApiLogDO.setStatusCode( result.getString("code") + "" );
                gkDeviceCenterApiLogDO.setResponseResult( result.toJSONString() );
                gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.SAVEATTACHMENTFILE );
            }
            return result;
        }catch (Exception e){
            throw exception("同步文件至设备中心失败，异常：" + e );
        }
    }

    @Override
    public JSONObject syncDeleteFile(EqtFileDeleteVO eqtFileDeleteVO) {

        //插入日志
        GkDeviceCenterApiLogDO gkDeviceCenterApiLogDO = new GkDeviceCenterApiLogDO();
        gkDeviceCenterApiLogDO.setRequestParam( JSONObject.toJSONString( eqtFileDeleteVO ) );

        ForestResponse<JSONObject> jsonObjectForestResponse = eqtFileClient.deleteAttachmentFile(EqtCenterUtil.doPostJsonHeader(JSON.toJSONString(eqtFileDeleteVO)), eqtFileDeleteVO);
        log.info("调用设备中心同步删除附件接口返回信息{}", jsonObjectForestResponse);
        if ( !jsonObjectForestResponse.isSuccess() ){
            gkDeviceCenterApiLogDO.setStatusCode( jsonObjectForestResponse.statusCode() + "" );
            gkDeviceCenterApiLogDO.setResponseResult( jsonObjectForestResponse.getContent() );
            gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.DELETEATTACHMENTFILE );
            throw exception("调用设备中心同步附件接口失败");
        }
        if ( (jsonObjectForestResponse.getResult().get("code") != null && !jsonObjectForestResponse.getResult().get("code").toString().equals("200")) ){
            gkDeviceCenterApiLogDO.setStatusCode( jsonObjectForestResponse.getResult().get("code") + "" );
            gkDeviceCenterApiLogDO.setResponseResult( jsonObjectForestResponse.getResult().toJSONString() );
            gkDeviceCenterApiLogService.createLog( gkDeviceCenterApiLogDO, DeviceCenterApiEnum.DELETEATTACHMENTFILE );
            throw exception("调用设备中心删除接口失败：" + (jsonObjectForestResponse.getResult().get("msg") != null ? jsonObjectForestResponse.getResult().get("msg").toString() : ""));
        }
        return jsonObjectForestResponse.getResult();
    }

    /**
     * 同步附件到设备中心
     * @param url
     * @param file
     * @param eqtFileDto
     * @return
     */
    public String senFile(String url, File file, EqtFileDto eqtFileDto) {
         // filepath表示文件路径 paramMap表示其他参数
        // 创建httpPost

        String httpUrl = deviceCenterAddress + url;
        HttpPost httpPost = new HttpPost( httpUrl );
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        org.apache.http.HttpEntity entity = null;
        String responseContent = null;
        try {

            // 设置参数
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            //调用的url的文件的参数是file 需要根据调用的url需要的参数进行修改
            multipartEntityBuilder.addBinaryBody( "file", file );//表单中其他参数
            if (eqtFileDto != null) {
                multipartEntityBuilder.addPart("bureauCode", new StringBody(eqtFileDto.getBureauCode(), org.apache.http.entity.ContentType.create("text/plain", Consts.UTF_8)));

                multipartEntityBuilder.addPart("modelAttachmentInfo", new StringBody(eqtFileDto.getModelAttachmentInfo().toJSONString(), org.apache.http.entity.ContentType.create("application/json", Consts.UTF_8)));
            }
            org.apache.http.HttpEntity reqEntity = multipartEntityBuilder.build();
            httpPost.setEntity(reqEntity);
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            // 执行请求
            response = httpClient.execute(httpPost);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            log.error("<<<<<< HttpUtil sendData error cause {}", e);
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                log.error("<<<<<< HttpUtil sendData error cause {}", e);
            }
        }
        return responseContent;
    }
}
